package ik.xcj.hostpital.manage.service.Impl;

import com.alibaba.fastjson.JSON;
import ik.xcj.hostpital.manage.ex.ServiceException;
import ik.xcj.hostpital.manage.mapper.IRoleMapper;
import ik.xcj.hostpital.manage.mapper.UserMapper;
import ik.xcj.hostpital.manage.mapper.UserRoleMapper;
import ik.xcj.hostpital.manage.pojo.dto.*;
import ik.xcj.hostpital.manage.pojo.entity.User;
import ik.xcj.hostpital.manage.pojo.entity.UserRole;
import ik.xcj.hostpital.manage.pojo.vo.*;
import ik.xcj.hostpital.manage.security.UserDetails;
import ik.xcj.hostpital.manage.security.YzmUtil;
import ik.xcj.hostpital.manage.service.UserService;
import ik.xcj.hostpital.manage.web.ServiceCode;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private IRoleMapper roleMapper;

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    PasswordEncoder passwordEncoder;
    @Value("${hostpital.manage.jwt.secret-key}")
    private String secretKey;

    @Value("${hostpital.manage.jwt.duration-in-minute}")
    private long durationInMinute;

    @Override
    public String login(UserLoginDTO userLoginDTO) {
        log.debug("开始处理【管理员登录】的业务，参数为：{}",userLoginDTO);
        //执行认证
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                userLoginDTO.getUsername(),userLoginDTO.getPassword());
        Authentication authenticationResult = authenticationManager.authenticate(authentication);
        log.debug("认证通过，认证结果：{}",authenticationResult);
        log.debug("认证通过，认证结果中的当事人：{}",authenticationResult.getPrincipal());

        //jwt生成稍后再说
        //将通过认证的管理员的相关信息存入jwt中
        //准备生成jwt的相关数据
        Date date = new Date(System.currentTimeMillis() + durationInMinute * 60 * 1000);
        UserDetails principal = (UserDetails) authenticationResult.getPrincipal();
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", principal.getId());
        claims.put("username", principal.getUsername());
        Collection<GrantedAuthority> authorities = principal.getAuthorities();
        String authoritiesJsonString = JSON.toJSONString(authorities);
        claims.put("authoritiesJsonString", authoritiesJsonString);
        String jwt = Jwts.builder().
                setHeaderParam("alg", "HS256").
                setHeaderParam("typ", "JWT").
                setClaims(claims).
                setExpiration(date).
                signWith(SignatureAlgorithm.HS256, secretKey).
                compact();
        return jwt;

    }

    //注册
    @Override
    public void insert(UserRegDTO userRegDTO) {
        log.debug("开始处理【用户注册】的业务，参数：{}",userRegDTO);
        int countByUsername = userMapper.countByUsername(userRegDTO.getUsername());
        log.debug("countByUsername：{}",countByUsername);
        if (countByUsername>0){
            throw new ServiceException(ServiceCode.ERR_CONFLICT,"注册失败，用户名已经存在");
        }
        int countByPhone = userMapper.countByPhone(userRegDTO.getPhone());
        log.debug("countByPhone：{}",countByPhone);
        if (countByPhone>0){
            throw new ServiceException(ServiceCode.ERR_CONFLICT,"注册失败，手机号已注册");
        }
        User user = new User();
        String password = userRegDTO.getPassword();
        log.debug("password：{}",password);
        String encode = passwordEncoder.encode(password);
        log.debug("encode：{}",encode);
        BeanUtils.copyProperties(userRegDTO,user);
        log.debug("user：{}",user);
        user.setPassword(encode);
        user.setAuthStatus(2);
        user.setStatus(1);
        user.setIsDeleted(0);
        user.setCreateTime(Timestamp.valueOf(LocalDateTime.now()));
        user.setUpdateTime(Timestamp.valueOf(LocalDateTime.now()));
        log.debug("user：{}",user);
        int rows = userMapper.insert(user);
        if (rows!=1){
            throw new ServiceException(ServiceCode.ERR_INSERT,"注册失败,服务器繁忙");
        }

        //添加默认角色
        UserRole userRole=new UserRole();
        //用户ID
        userRole.setUserId(user.getId());
        //默认角色ID为普通用户
        userRole.setRoleId(2L);
        log.debug("userRole：{}",userRole);
        int insert = userRoleMapper.insert(userRole);
        log.debug("insert：{}",insert);
        if (insert!=1){
            throw new ServiceException(ServiceCode.ERR_INSERT,"填写默认权限失败!");
        }

    }
    //手机号登录
    @Override
    public String loginByPhone(UserLoginByPhoneDTO userLoginByPhoneDTO) {
        log.debug("开始处理【手机号登录】的业务，参数：{}",userLoginByPhoneDTO);
        String phone=userLoginByPhoneDTO.getPhone()+"YZM";
        int count = userMapper.countByPhone(userLoginByPhoneDTO.getPhone());
        if (count != 1){
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"登录失败，手机号不存在");
        }
        String redisCode=redisTemplate.opsForValue().get(phone);
        if (redisCode==null){
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"请发送验证码");
        }

        if (!redisCode.equalsIgnoreCase(userLoginByPhoneDTO.getCode())){
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"验证码错误");
        }
        return "登录成功！";
    }
    //发送手机验证码
    @Override
    public void senPhone(String phone) {
        String phone1=phone+"YZM";

        String redisCode=redisTemplate.opsForValue().get(phone1);
        System.out.println("redisCode = " + redisCode);
        if(redisCode!=null){
            throw new ServiceException(ServiceCode.ERR_CONFLICT,"发送失败");
        }

        UserLoginInfoVO user = userMapper.selectByPhone(phone);
        if (user==null){
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"手机号不存在");
        }

        YzmUtil yzm=new YzmUtil();
        String yzm1= yzm.Yzm();

        //将验证码加入缓冲
        redisTemplate.opsForValue().set(phone1, yzm1,1, TimeUnit.MINUTES);
    }
    @Override
    public UserLoginByUserNameAndRoleVO selectByPhone(String phone) {
        return userMapper.getByPhone(phone);
    }

    @Override
    public UserLoginByUserNameAndRoleVO selectByUserName(String username) {
        return userMapper.selectByUserName(username);
    }
    /*用户管理*/
    //增
    @Override
    public void addNew(UserAddNewDTO userAddNewDTO) {
        log.debug("开始处理【用户管理】的业务，参数：{}",userAddNewDTO);
        int countByUsername = userMapper.countByUsername(userAddNewDTO.getUsername());
        if (countByUsername >0){
            throw new ServiceException(ServiceCode.ERR_CONFLICT,"用户名已存在");
        }
        int countByPhone = userMapper.countByPhone(userAddNewDTO.getPhone());
        if (countByPhone >0){
            throw new ServiceException(ServiceCode.ERR_CONFLICT,"手机号已存在");
        }

        User user = new User();
        user.setStatus(1);
        BeanUtils.copyProperties(userAddNewDTO,user);
        user.setCreateTime(Timestamp.valueOf(LocalDateTime.now()));
        int rows = userMapper.insert(user);
        if (rows !=1){
            String message = "添加用户失败,服务器忙,请稍后再试! ";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        };
        //添加默认角色
        UserRole userRole=new UserRole();
        //用户ID
        userRole.setUserId(user.getId());
        //默认角色ID为普通用户
        userRole.setRoleId(2L);
        int insert = userRoleMapper.insert(userRole);
        if (insert!=1){
            throw new ServiceException(ServiceCode.ERR_INSERT,"填写默认权限失败!");
        }
    }
    //删除
    @Override
    public void deleteById(Long id) {
        log.debug("开始处理【删除用户】的业务，参数：{}",id);
        int countById = userMapper.countById(id);
        if (countById != 1){
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"删除用户失败，该用户不存在");
        }
        int rows = userMapper.deleteById(id);
        if (rows !=1){
            String message = "删除用户失败,服务器忙,请稍后再试! ";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        };
        rows = userRoleMapper.deleteByUserId(id);
        if (rows !=1){
            String message = "删除用户失败,服务器忙,请稍后再试! ";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        };
    }
    //修改
    @Override
    public void updateInfoById(Long id, UserUpdateDTO userUpdateDTO) {
        log.debug("开始处理【修改用户信息】的业务，id={},新的数据={}",id,userUpdateDTO);
        int countByPhone = userMapper.countByPhone(userUpdateDTO.getPhone());
        if (countByPhone >0){
            throw new ServiceException(ServiceCode.ERR_CONFLICT,"手机号已存在");
        }
        User user = new User();
        user.setId(id);
        user.setStatus(1);
        user.setIsDeleted(0);
        BeanUtils.copyProperties(userUpdateDTO,user);
        user.setUpdateTime(Timestamp.valueOf(LocalDateTime.now()));
        int rows = userMapper.update(user);
        if (rows !=1){
            String message = "修改用户失败,服务器忙,请稍后再试! ";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        };
//        //添加默认角色
//        UserRole userRole=new UserRole();
//        //用户ID
//        userRole.setUserId(id);
//        //默认角色ID为普通用户
//        RoleStandardVO standardByName = roleMapper.getStandardByName(userUpdateDTO.getRoleName());
//        userRole.setRoleId(standardByName.getId());
//        int insert = userRoleMapper.insert(userRole);
//        if (insert!=1){
//            throw new ServiceException(ServiceCode.ERR_INSERT,"填写默认权限失败!");
//        }
    }
    //根据id查找
    @Override
    public UserStandardVO getStandardById(Long id) {
        log.debug("开始处理【根据id查找用户数据】，参数：{}",id);
        UserStandardVO userStandardById = userMapper.getStandardById(id);
        if (userStandardById == null){
            String message ="查找用户数据失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }
        log.debug("即将返回查询结果",userStandardById);
        return userStandardById;
    }
    //根据用户名查找
    @Override
    public UserStandardVO getStandardByUsername(String username) {
        log.debug("开始处理【根据用户名查找用户数据】，参数：{}",username);
        UserStandardVO userStandardByUsername = userMapper.getStandardByUsername(username);
        if (userStandardByUsername == null){
            String message ="查找用户数据失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }
        log.debug("即将返回查询结果",userStandardByUsername);
        return userStandardByUsername;
    }
    //根据手机号查找
    @Override
    public UserStandardVO getStandardByPhone(String phone) {
        log.debug("开始处理【根据手机号查找用户数据】，参数：{}",phone);
        UserStandardVO userStandardByPhone = userMapper.getStandardByPhone(phone);
        if (userStandardByPhone == null){
            String message ="查找用户数据失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,message);
        }
        log.debug("即将返回查询结果",userStandardByPhone);
        return userStandardByPhone;
    }
    //查找用户列表
    @Override
    public List<UserListItemVO> list() {
        log.debug("开始处理【查询用户列表】的业务，参数：无");
        List<UserListItemVO> userList = userMapper.list();
        log.debug("即将返回查询结果：{}",userList);
        return userList;
    }

}


